package au.edu.adelaide.mips_soft_core.board_interface_pc.ui;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;

import au.edu.adelaide.mips_soft_core.board_interface_pc.core.Core;
import au.edu.adelaide.mips_soft_core.board_interface_pc.core.CoreListener;
import au.edu.adelaide.mips_soft_core.board_interface_pc.core.Device;
import au.edu.adelaide.mips_soft_core.board_interface_pc.core.DeviceListener;

public class DownloadMemoryPanel extends JPanel implements ActionListener, ItemListener, CoreListener, DeviceListener{
	
	private String empty_string = "<Empty>";
	
	JComboBox<String> memoryModuleSelector = new JComboBox<String>();
	
	JButton selectFileButton = new JButton("Select Binary Output File");
	JButton downloadButton = new JButton("DOWNLOAD!");
	
	JRadioButton leaveByteOrder = new JRadioButton("Leave");
	JRadioButton swapByteOrder = new JRadioButton("Swap");
	
	ButtonGroup group = new ButtonGroup();
	{
		group.add(leaveByteOrder);
		group.add(swapByteOrder);
		swapByteOrder.setSelected(true);
		leaveByteOrder.setEnabled(false);
		swapByteOrder.setEnabled(false);
	}
	
	File file = null;
	
	Device connectedDevice = null;
	
	int memSize = -1;
	
	JLabel availableSize = new JLabel();
	
	
	public DownloadMemoryPanel(){
		super(new GridBagLayout());
		addComponent(this, new JLabel("Memory Module"), 0, 0, 1, 1);
		addComponent(this, memoryModuleSelector, 1, 0, 1, 1);
		addComponent(this, new JLabel("Size"), 0, 1, 1, 1);
		addComponent(this, availableSize, 1, 1, 1, 1);
		addComponent(this, selectFileButton, 0, 2, 2, 1);
		JPanel panel = new JPanel();
		addComponent(this, panel, 0, 3, 2, 1);
		panel.setBorder(BorderFactory.createTitledBorder("Byte Order"));
		panel.add(leaveByteOrder);
		panel.add(swapByteOrder);
		addComponent(this, downloadButton, 0, 4, 2, 1);
		downloadButton.setEnabled(false);
		this.downloadButton.addActionListener(this);
		this.selectFileButton.addActionListener(this);
		memoryModuleSelector.addItemListener(this);
		Core.getCore().addCoreListener(this);
	}
	
	private void addComponent(JPanel panel, JComponent component, int x, int y, int width, int height){
		 GridBagConstraints c = new GridBagConstraints();
		 c.gridx = x;
		 c.gridy = y;
		 c.gridheight = height;
		 c.gridwidth = width;
		 panel.add(component,  c);
	}
	
	public void actionPerformed(ActionEvent e) {
		if(e.getSource() == this.selectFileButton){
			JFileChooser jfc = new JFileChooser("Select File");
			String filePath = Preferences.getValue("DownloadLastFilePath");
			if(filePath != null){
				File f = new File(filePath);
				if(f.exists()){
					jfc.setSelectedFile(f);
				}
			}
			int result = jfc.showSaveDialog(this);
			if(result != JFileChooser.APPROVE_OPTION){
				return;
			}
			Preferences.setValue("DownloadLastFilePath", jfc.getSelectedFile().getPath());
			this.file = jfc.getSelectedFile();
			this.downloadButton.setEnabled(true);
		}else if(e.getSource() == this.downloadButton){
			try {
				FileOutputStream outFile = new FileOutputStream(this.file);
				connectedDevice.downloadFromBoardMemory(this.memoryModuleSelector.getSelectedIndex(), 0, connectedDevice.getSizeOfMemoryModule((byte)this.memoryModuleSelector.getSelectedIndex()) * 4, outFile);
				outFile.close();
				Core.getCore().getLogger().write("DONE Downloading From BOARD", Core.LOG_LEVEL_MESSAGE);
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			
		}
	}
	
	void changeSelected(int index){
		
		if(index == -1){
			disablePanel();
			return;
		}
		String selected = this.memoryModuleSelector.getItemAt(index);
		if(selected == empty_string){
			disablePanel();
			return;
		}
		enablePanel();
		this.memSize = this.connectedDevice.getSizeOfMemoryModule(Byte.parseByte(selected));
		this.availableSize.setText(this.memSize + " words");
	}
	
	void disablePanel(){
		this.availableSize.setText("-");
	}
	
	void enablePanel(){
		
	}
	
	void updateMemoryModules(){
		this.memoryModuleSelector.removeAllItems();
		if(this.connectedDevice == null){
			this.memoryModuleSelector.addItem(empty_string);
			return;
		}
		for(int i = 0; i < this.connectedDevice.getNumberOfMemoryModules(); i++){
			this.memoryModuleSelector.addItem(Integer.toString(i));
		}
	}

	@Override
	public void itemStateChanged(ItemEvent e) {
		if(e.getStateChange() == ItemEvent.SELECTED){
			changeSelected(this.memoryModuleSelector.getSelectedIndex());
		}
		
	}

	@Override
	public void error(String message) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void boardDiagnosed() {
		updateMemoryModules();
	}

	@Override
	public void modeChanged() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void deviceListChanged() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void deviceConnected(Device device) {
		this.connectedDevice = device;
		device.addDeviceListener(this);
		
	}

	@Override
	public void deviceDisconnected(Device device) {
		this.connectedDevice = null;
		device.removeListener(this);
		
	}

}
